/*! \file
 * \brief Implementation file for the file-input.
 * \author Ivo Wingelaar
 * \date 2011
 * \version 0.1.0
 * \copyright GNU Lesser General Public License v3
 */

#include "MythFile_InputFile_C.hpp"

namespace Myth
{
namespace File
{

//! Creates an input from a file.
/*!
 * \param[in] stream_name Name of the stream.
 * \param[in] file_name Path to the file you want to open for reading.
 */
InputFile_C::InputFile_C(const std::string& stream_name, const std::string& file_name) :
    Input(stream_name),
    mFile(0),
    mFileSize(0),
    mFileName(file_name)
{
    open_file();
}

//! Virtual destructor.
InputFile_C::~InputFile_C(void)
{
    if(mFile != NULL)
        fclose(mFile);
}

//! Reads an amount of bytes from the input.
/*!
 * \return The number of bytes actually read.
 * \param[out] buffer The place to store the data.
 * \param[in] size The number of bytes to request.
 * \throw InputException if something went wrong.
 */
uintptr_t InputFile_C::read(void* buffer, uintptr_t size)
{
    return (int32_t)fread(buffer, 1, size, mFile);
}

//! Changes the position in the data-input.
/*!
 * \return If the specifief position was reached true is returned, false otherwise.
 * \param[in] position The position you want to seek to.
 * \param[in] relative Should we change the position relative to this, or absolute?
 */
bool InputFile_C::seek(uintptr_t position, bool relative)
{
    return (fseek(mFile, position, relative ? SEEK_CUR : SEEK_SET) == 0);
}

//! Returns the size of the input.
/*!
 * \return The size of the input.
 */
uintptr_t InputFile_C::get_size(void) const
{
    return mFileSize;
}

//! Returns the current position of the input.
/*!
 * \return The current position of the input.
 */
uintptr_t InputFile_C::get_pos(void) const
{
    return (uintptr_t)ftell(mFile);
}

//! Return if the file was opened succesfuly
/*!
 * \return True if the file was opened, false otherwise.
 */
bool InputFile_C::is_open(void) const
{
    return (mFile != NULL);
}

//! Tries to open the file.
void InputFile_C::open_file(void)
{
    if(mFileName.size() == 0)
    {
        mFile = NULL;
        return;
    }

    mFile = fopen(mFileName.c_str(), "rb");

    if(mFile != NULL)
    {
        fseek(mFile, 0, SEEK_END);
        mFileSize = get_pos();
        rewind(mFile);
    }
}

} // namespace File
} // namespace Myth
